/*
 * Copyright (C) 2014
 *
 * Brick Yang <printfxxx@163.com>
 *
 * This program is free software. You can redistribute it and/or
 * modify it as you like.
 */

/**
 * @file	worker.h
 * @brief	Header file for worker
 */

#ifndef _WORKER_H_
#define _WORKER_H_

#include <linux/mutex.h>
#include <linux/cpumask.h>

enum {
	WORKER_OP_WORKER,		/* Get worker status */
	WORKER_OP_REG,			/* Register a poll instance */
	WORKER_OP_UNREG,		/* Unregister a poll instance */
	WORKER_OP_BIND,			/* Bind a netdev */
	WORKER_OP_UNBIND,		/* Unbind a netdev */
	WORKER_OP_START,		/* Start traffic on netdev */
	WORKER_OP_STOP,			/* Stop traffic on netdev */
	WORKER_OP_FREE,			/* Unbind all netdev */
	WORKER_OP_FC,			/* Flow control configuration */
	WORKER_OP_QUEUE,		/* Queue configuration */
	WORKER_OP_POOL_SZ,		/* Set pool size */
	WORKER_OP_PKT_CNT,		/* Set packets count */
	WORKER_OP_ADD_PKT,		/* Add pkts */
	WORKER_OP_DEL_PKT,		/* Delete pkts */
	WORKER_OP_PKT_TXQ,		/* Set txq mapping of pkts */
	WORKER_OP_DUMP_PKT,		/* Dump pkts */
	WORKER_OP_MAXIMUM,
#define WORKER_OP_F_EXCLUSIVE	0x40000000
#define WORKER_OP_F_PARALLEL	0x80000000
};

typedef struct worker_op {
	unsigned int opcode;
	cpumask_t cpumask;
#define get_arg(var, ptr)	do { var = *((typeof(var) *)(ptr)); } while (0)
#define set_arg(ptr, var)	do { ptr = (typeof(ptr))&var; } while (0)
	void *args[6];
} worker_op_t;

typedef struct worker {
	worker_op_t *op;
	unsigned int cpu;
	int op_resp;
	struct task_struct *th;
	struct list_head poll_list;
	struct list_head flow_list;
	wait_queue_head_t op_wq, resp_wq;
	struct mutex op_lock;
} worker_t;

typedef void (poll_fn_t)(void *arg);

extern struct cpumask		__worker_cpumask;
#define worker_cpumask		((const struct cpumask *)&__worker_cpumask)

int worker_op_post(worker_op_t *op);
worker_t *worker_get(unsigned int cpu);
void get_worker_cpumask(struct cpumask *cpumask);
__init int worker_init_all(void);
void worker_cleanup_all(void);
int sb_worker_reg_poll(const char *name, poll_fn_t *fn, void *arg);
void sb_worker_unreg_poll(const char *name, poll_fn_t *fn, void *arg);

#endif	/* _WORKER_H_ */
